#!/bin/bash

#=============================================================================
# 脚本名称: extract_audio.sh
# 功能描述: 批量从MP4视频文件中提取音频并转换为MP3格式
# 作者: Pedro.Pei
# 版本: 1.0
# 日期: 2024-12-20
#=============================================================================

# 功能说明:
# 本脚本用于批量处理指定目录中的视频文件，提取其中的音频轨道并保存为MP3格式
# - 自动扫描目录中的所有支持格式的视频文件
# - 支持多种视频格式：MP4, MOV, AVI, MKV, WMV, FLV, WebM, M4V
# - 使用ffmpeg进行高质量音频提取
# - 输出文件保存到源目录下的audio_extracted子文件夹
# - 提供实时进度显示和详细的处理日志
# - 支持彩色输出显示成功/失败状态

# 输出格式:
# 原文件: example.mp4 -> 输出文件: example_audio.mp3
# 所有提取的音频文件都会添加"_audio"后缀以区分原文件

# 使用方法:
# ./extract_audio.sh <源目录路径>
#
# 参数说明:
# <源目录路径>    必需参数，指定包含MP4文件的目录路径
#                支持相对路径和绝对路径

# 使用示例:
# ./extract_audio.sh /path/to/videos          # 处理指定目录中的视频文件
# ./extract_audio.sh ./videos                 # 处理当前目录下的videos文件夹
# ./extract_audio.sh ~/Downloads/movies       # 处理用户下载目录中的电影文件

# 输出结构:
# 源目录/
# ├── video1.mp4
# ├── video2.mp4
# └── audio_extracted/
#     ├── video1_audio.mp3
#     ├── video2_audio.mp3
#     └── extraction_log.txt

# 依赖要求:
# - ffmpeg: 用于音频提取和格式转换
# - bash: 脚本运行环境
# - realpath: 用于路径解析（通常系统自带）

# 安装ffmpeg (如果未安装):
# macOS: brew install ffmpeg
# Ubuntu/Debian: sudo apt install ffmpeg
# CentOS/RHEL: sudo yum install ffmpeg

# 特性说明:
# - 高质量音频提取 (使用-q:a 0参数)
# - 实时进度显示 (显示当前处理文件和总进度)
# - 详细日志记录 (包含每个文件的处理时间)
# - 错误处理机制 (统计成功和失败的文件数量)
# - 彩色输出支持 (绿色表示成功，红色表示失败)
# - 自动创建输出目录

# 注意事项:
# - 脚本支持多种常见视频格式（MP4, MOV, AVI, MKV, WMV, FLV, WebM, M4V）
# - 需要确保有足够的磁盘空间存储提取的音频文件
# - 处理大文件时可能需要较长时间
# - 如果ffmpeg未安装，脚本将无法正常工作
# - 输出的MP3文件质量设置为最高质量

#=============================================================================

# 检查是否提供了源目录参数
if [ -z "$1" ]; then
  echo "Usage: $0 <source_directory>"
  exit 1
fi

# 获取并验证源目录
input_dir=$(realpath "$1")
if [ ! -d "$input_dir" ]; then
  echo "Error: Source directory '$1' does not exist."
  exit 1
fi

# 定义输出目录为源目录下的 'audio_extracted' 子文件夹
output_dir="$input_dir/audio_extracted"
mkdir -p "$output_dir"

# 初始化日志文件
log_file="$output_dir/extraction_log.txt"
echo "Starting audio extraction at $(date)" > "$log_file"

# 记录脚本开始时间
start_time=$(date +%s)

# 支持的视频格式
video_extensions=("mp4" "mov" "avi" "mkv" "wmv" "flv" "webm" "m4v")

# 收集所有支持的视频文件
video_files=()
for ext in "${video_extensions[@]}"; do
  # 处理小写扩展名
  for file in "$input_dir"/*.$ext; do
    if [ -f "$file" ]; then
      video_files+=("$file")
    fi
  done
  # 处理大写扩展名
  ext_upper=$(echo "$ext" | tr '[:lower:]' '[:upper:]')
  for file in "$input_dir"/*.$ext_upper; do
    if [ -f "$file" ]; then
      video_files+=("$file")
    fi
  done
done

total_files=${#video_files[@]}
if [ $total_files -eq 0 ]; then
  echo "No supported video files found in the source directory."
  echo "Supported formats: ${video_extensions[*]}"
  exit 0
fi

# 初始化计数器
success_count=0
failure_count=0
current_file=0

# 打印初始信息
echo "Found $total_files video files to process."
echo "Supported formats: ${video_extensions[*]}"
echo ""

# 遍历所有的视频文件
for file in "${video_files[@]}"; do
  # 检查是否确实是一个文件
  if [ -f "$file" ]; then
    # 更新进度
    current_file=$((current_file + 1))
    printf "\rProcessing file %d of %d: %s" "$current_file" "$total_files" "$(basename "$file")"
    
    # 记录任务开始时间
    task_start_time=$(date +%s)
    
    # 获取不带扩展名的文件名
    filename_with_ext="${file##*/}"
    filename_without_ext="${filename_with_ext%.*}"
    
    # 构建输出文件路径
    output_file="$output_dir/${filename_without_ext}_audio.mp3"
    
    # 提取音频并保存为MP3
    echo -e "\nExtracting audio from $file..." >> "$log_file"
    ffmpeg -i "$file" -q:a 0 "$output_file" >> "$log_file" 2>&1
    
    # 检查ffmpeg命令是否成功执行
    if [ $? -eq 0 ]; then
      # 记录任务结束时间
      task_end_time=$(date +%s)
      task_duration=$((task_end_time - task_start_time))
      echo "Successfully extracted audio from $file to $output_file (took $task_duration seconds)" >> "$log_file"
      success_count=$((success_count + 1))
      echo -e "\r\033[32mSuccessfully extracted audio from $file to $output_file (took $task_duration seconds)\033[0m"
    else
      # 记录任务结束时间
      task_end_time=$(date +%s)
      task_duration=$((task_end_time - task_start_time))
      echo "Failed to extract audio from $file (took $task_duration seconds)" >> "$log_file"
      failure_count=$((failure_count + 1))
      echo -e "\r\033[31mFailed to extract audio from $file (took $task_duration seconds)\033[0m"
    fi
  fi
done

# 记录脚本结束时间
end_time=$(date +%s)
total_duration=$((end_time - start_time))

# 打印总结信息
echo -e "\n音频提取已完成。"
echo "已处理的文件总数: $total_files"
echo "成功提取: $success_count"
echo "提取失败: $failure_count"
echo "总耗时: $total_duration seconds"
echo "检查日志文件以了解详细信息: $log_file"
